/*
-----------------------------------------------------------------------------
This source file is part of Labor3D
(Labor 3D Graphics Engine)

Copyright (c) 2009-2020 Rock Mao
* creator : Rock Mao
* created : 2010-5-28   21:45
* filename: LFilePack.h

-----------------------------------------------------------------------------
*/

#ifndef __LFILEPACK_H__
#define __LFILEPACK_H__

#include "LFilePackImp.h"

class CLDirFPBuilder;
class CLFPInStream;

class CLFilePack
{
	vector<sFPDataEntry>     m_listDataEntry;
	wchar_t                  m_file_name[FILENAMELENGTH];
	sFPFileHeader            m_FileHeader;
	LOpenMode                m_eMode;
	sFPHashTableItem*        m_pHashTable;
	wstring                  m_BaseDir;

	/// read stream
	ifstream                 m_readStream;
	lfpState                 m_eState;
	friend class CLDirFPBuilder;
public:
	CLFilePack();
	~CLFilePack();

	bool          open(const wchar_t* file_name, LOpenMode eOpenMode, bool bCreate = false );
	bool          save();
	bool          addFile( const wchar_t* file_name);
	
	CLFPInStream* unwrapBuffer( const wchar_t* name );
	bool          unwrapFile( const wchar_t* name, const wchar_t* file_name );
	bool          pack_dir(const wchar_t* dir);
	bool          unpack(const wchar_t* obj_dir );
	bool          close_stream( CLFPInStream* pStream );
	lfpState      state() {return m_eState; }
protected:
	bool create(const wchar_t* file_name,int hash_table_size=256);
	bool _fill_header();
	bool _write_data_to_stream(ostream& stream);
	bool _unpack_data( const wchar_t* file_name, sFPDataEntryInfo& entryInfo );


	/// hashtable
	void __init_hash_table(int hash_table_size);
	void __clear_hash_table();
	void __resize_hash_table(int hash_table_size);
	void __recalculate_hash_table();
	void __fit_hash_table();
	int  __find_hash_index(const wchar_t* name);



	/// file operator
	bool __insert_data( const wchar_t* name, const wchar_t* full_name = NULL, lfp_data_type type = lfpdt_file, int compress_rate = -1 );
	bool __insert_file( const wchar_t* name,const wchar_t* full_name , lfp_data_type type = lfpdt_file, int compress_rate = -1 );
	bool __insert_buffer( const wchar_t* name, int compress_rate = -1 );
    //// 
	int __calDataEntryPoint();

	/// read
	bool __open_for_read(const wchar_t* file_name);
	bool __open_for_read(ifstream & stream);
	/// unwarp
	CLFPInStream* __unwrapBuffer(int nHashIndex );
	CLFPInStream* __unwrapBuffer( sFPDataEntryInfo& entryInfo );


	/// cal addr
	int __getDataEntryListStart();
	int __getDataStart();

	/// file identify
	void __fill_file_header();
	bool __check_file_header();

};
#endif